#include <mbed.h>
#ifdef TARGET_UNO_91H
#include "WiFiStackInterface.h"
#include "baidu_wifi_ssid_config.h"
#else
#include "EthernetInterface.h"
#endif

#define LOG(_fmt, ...)  mbed_error_printf("%s(%4d): [%s] "_fmt"\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)

#define BUFFER_SIZE         (1024)

#ifndef TCP_TEST_HOST
#define HOST    "yinyueshiting.baidu.com"
#else
#define HOST    TCP_TEST_HOST
#endif

#ifndef TCP_TEST_PORT
#define PORT    80
#else
#define PORT    TCP_TEST_PORT
#endif

#ifndef TCP_TEST_PATH
#define PATH    "/data2/music/fcb085c9d1553a21d8a858a359a8b886/274961849/274961734252000128.mp3?xcode=ce8a4c9c910e6be5f5d44a3a1acfff98"
#else
#define PATH    TCP_TEST_PATH
#endif

#ifndef INTERUPT_TIMEOUT
#define INTERUPT_TIMEOUT    (3000) // ms
#endif

#ifndef PERIOD_DELAY
#define PERIOD_DELAY        (800) // ms
#endif

#ifdef TARGET_UNO_91H
static WiFiStackInterface nif;
#else
static EthernetInterface nif;
#endif

static const char g_http_header[] =
    "GET "PATH" HTTP/1.1\r\n"
    "User-Agent: tcp test\r\n"
    "Host: "HOST"\r\n"
    "Accept: */*\r\n"
    "\r\n";

void dump_stat(const char *token, int bytes, int millis) {
    if (token == NULL) {
        token = "DUMP";
    }

    LOG("[%s] read: %8d bytes, spent: %4d ms, speed: %f kbps",
        token, bytes, millis,
        1.0f * bytes * 1024 * 8 / millis / 1000);
}

void download(void) {
    int rs;
    char buff[BUFFER_SIZE];
    mbed::Timer timer;
    timer.start();

    while (true) {
        TCPSocket socket(&nif);
        rs = socket.connect(HOST, PORT);
        if (rs < NSAPI_ERROR_OK) {
            LOG("connect rs = %d", rs);
            break;
        }

        LOG("CONNECTED!!!");

        rs = socket.send(g_http_header, strlen(g_http_header));
        if (rs < NSAPI_ERROR_OK) {
            LOG("send rs = %d", rs);
            break;
        }

        //LOG("SENT: \n%s", g_http_header);

        int total = 0, period = 0;
        int begin = timer.read_ms();
        int end;
        int cur = begin;

        while ((rs = socket.recv(buff, BUFFER_SIZE)) > NSAPI_ERROR_OK) {
            period += rs;
            end = timer.read_ms();
            if (end - cur > PERIOD_DELAY) {
                dump_stat("PERIOD", period, end - cur);
                cur = end;
                total += period;
                period = 0;
            }
#if defined(INTERUPT_TIMEOUT) && (INTERUPT_TIMEOUT > 0)
            if (end - begin > INTERUPT_TIMEOUT) {
                break;
            }
#endif
        }

        if (period > 0 && end - cur > 0) {
            dump_stat("PERIOD", period, end - cur);
            total += period;
            period = 0;
        }

        dump_stat("FINISHED", total, end - begin);

        if (rs < NSAPI_ERROR_OK) {
            LOG("recv rs = %d", rs);
            break;
        }

        rs = socket.close();
        if (rs < NSAPI_ERROR_OK) {
            LOG("close rs = %d", rs);
            break;
        }
    }
}

int main(void) {
    int rs;

#ifdef TARGET_UNO_91H
    rs = nif.connect(BD_NET_STACK_SOC_WIFI_SSID, BD_NET_STACK_SOC_WIFI_PASS, NSAPI_SECURITY_NONE);
#else
    rs = nif.connect();
#endif
    if (rs == 0) {
        LOG("IP address is:\t%s\n", nif.get_ip_address());
        LOG("MAC address is:\t%s\n", nif.get_mac_address());
    } else {
        LOG("Network initial failed....");
        Thread::wait(osWaitForever);
    }

    Thread downloader;

    downloader.start(download);

    Thread::wait(osWaitForever);
    return 0;
}
